package com.tfjybj.itoo.exam.provider.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.dmsdbj.itoo.tool.base.service.impl.BaseServicePlusImpl;
import com.dmsdbj.itoo.tool.business.ItooResult;
import com.dmsdbj.itoo.tool.redis.CacheExpire;
import com.dmsdbj.itoo.tool.tojson.JacksonJsonUntil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tfjybj.itoo.exam.entity.OptionEntity;
import com.tfjybj.itoo.exam.entity.QuestionClassifyEntity;
import com.tfjybj.itoo.exam.entity.QuestionEntity;
import com.tfjybj.itoo.exam.model.*;
import com.tfjybj.itoo.exam.provider.dao.OptionDao;
import com.tfjybj.itoo.exam.provider.dao.QuestionDao;
import com.tfjybj.itoo.exam.provider.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.ibatis.annotations.Param;
import org.jplus.hyberbin.excel.utils.ExcelUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.IOException;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * QuestionService接口实现类
 * ${base}表
 *
 * @author 李青松
 * @version 2.0.0
 * @since 2.0.0 2018-11-01 08:55:53
 */
@Slf4j
@Service("questionService")
public class QuestionServiceImpl extends BaseServicePlusImpl<QuestionDao, QuestionEntity> implements QuestionService {

    //region 模板生成
    @Resource
    private QuestionService questionService;

    @Resource
    private OptionService optionService;

    @Resource
    private QuestionDao questionDao;

    @Resource
    private OptionDao optionDao;

    @Resource
    private QuestionTypeService questionTypeService;

    @Resource
    private OnlineExamService onlineExamService;

    @Resource
    private QuestionClassifyService questionClassifyService;

    @Resource
    private RedisTemplate<String, QuestionTemplate> redisTemplate;

    @Override
    public PageInfo<QuestionEntity> queryByLikeSerial(String serial, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);

        return new PageInfo<>(questionDao.queryLikeSerial(serial));
    }

    @Override
    public PageInfo<QuestionEntity> questionEntityPageInfo(Integer pageNum, Integer pageSize){
        PageHelper.startPage(pageNum,pageSize);
        return new PageInfo<>(questionDao.queryQuetionsByPage());
    }


    //endregion

    /* **********************************以下为非模板生成的内容********************************* */

    /**
     * 重写mybatisPlus的getById方法,为了重写缓存-王雪芬-2019年1月9日
     *
     * @param id
     * @return
     */
    @Cacheable(value = "byId", key = "#p0", unless = "#result == null")
    @CacheExpire(60)
    @Override
    public QuestionEntity getById(Serializable id) {
        return questionDao.selectById(id);
    }

    /**
     * 重写mybatisPlus的removeById方法,缓存-王雪芬-2019年1月9日
     *
     * @param id
     * @return
     */
    @Cacheable(value = "byId", key = "#p0", unless = "#result == null")
    @CacheExpire(60)
    @Override
    public boolean removeById(Serializable id) {
        int result = questionDao.deleteById(id);
        return result > 0;
    }

    /**
     * 重写mybatisPlus的updateById方法,缓存-王雪芬-2019年1月9日
     *
     * @param entity 题实体
     * @return
     */
    @Override
    @CacheEvict(value = "byId", key = "#p0.getId()")
    public boolean updateById(QuestionEntity entity) {
        int result = questionDao.updateById(entity);
        return result > 0;
    }


    /**
     * 把存在递归关系的题干拆分成子题-郭凯-2018年11月4日
     *
     * @param questionModels List
     * @return List
     * @author 郭凯
     */
    @Override
    public List<QuestionAddModel> queryProblem(List<QuestionAddModel> questionModels) {
        List<QuestionAddModel> problemModels = new ArrayList<>();
        for (QuestionAddModel questionModel : questionModels) {
            questionModel.setId(IdWorker.getIdStr());
            if (questionModel.getQuestionModel() != null && questionModel.getQuestionModel().size() > 0) {
                if (questionModel.getQuestionModel().get(0) == null) {
                    questionModel.setQuestionModel(null);
                }
            }
            if (CollectionUtils.isNotEmpty(questionModel.getQuestionModel())) {
                for (QuestionAddModel model : questionModel.getQuestionModel()) {
                    model.setParentId(questionModel.getId());
                }
                problemModels.addAll(queryProblem(questionModel.getQuestionModel()));
            }

            problemModels.add(questionModel);
        }

        return problemModels;
    }


    /**
     * 根据题干实体查询试题集合
     *
     * @param questionEntity QuestionEntity
     * @return List
     * @author 郭凯
     * @since 2.0.0 2018-11-8 15:47:09
     */
    @Override
    public List<QueryQuestionModel> queryByEntity(@Param("questionEntity") QuestionEntity questionEntity) {
        List<QueryQuestionModel> queryQuestionModelList = questionDao.queryByEntity(questionEntity);
        if (queryQuestionModelList.size() > 0) {
            return queryQuestionModelList;
        } else {
            return null;
        }
    }


    /**
     * 根据操作人查询试题集合
     *
     * @param operator 操作人
     * @return List
     * @author 郭凯
     * @since 2.0.0 2018-11-8 15:47:09
     */
    @Override
    public PageInfo<QuestionModelForHomePage> queryQuestionModelPageInfo(Integer pageNo, Integer pageSize, String operator) {
        PageHelper.startPage(pageNo, pageSize);
        return new PageInfo<QuestionModelForHomePage>(questionDao.queryByOperator(operator));
    }

    /**
     * @param operator       操作人
     * @param questionTypeId 问题类型id
     * @return java.util.List<com.tfjybj.itoo.exam.model.QuestionModelForHomePage>
     * @Description 检查题库问题
     * @author 刁琳童
     * @since 2.0.0 2019/3/24 8:38
     */
    @Override
    public List<QuestionModelForHomePage> checkRepeatedQuestions(String operator, String questionTypeId) {
        // 1. 根据题型id获取题型名称
        String questionTypeName = questionTypeService.getById(questionTypeId).getName().trim();
        // 2. 清空此题型的所有的check_result
        questionDao.updateClearCheckResult(operator, questionTypeId);
        // 3. 分题型来进行判断，如果有需要还可以进行拓展
        if ("判断题".contains(questionTypeName) || "单选题".equals(questionTypeName)  || "业务选择题".equals(questionTypeName) || "多选题".equals(questionTypeName)) {
            // 判断选项为空
            questionService.checkRadioNullQuestions(operator, questionTypeId);
            // 选项数量 < 4
            questionService.checkRadioNumQuestions(operator, questionTypeId);
            // 判断部分选项重复
            questionService.checkRadioRepeatQuestions(operator, questionTypeId);
            // 判断题干重复
            questionService.checkContentRepeatQuestions(operator, questionTypeId);
        } else {
            // 判断其他题型题干是否重复
            questionService.checkContentRepeatExecptRadioQuestions(operator, questionTypeId);
        }
        // 判断题干+答案是否完全相同
        questionService.checkCompleteRepeatQuestions(operator, questionTypeId);
        // 4. 返回查询结果
        return questionDao.checkResult(operator, questionTypeId);
    }



    /**
     *  分页 检查重复试题
     * @param pageNo
     * @param pageSize
     * @param operator
     * @param questionTypeId
     * @return
     * @author 杜雨
     * @since 1.0.0 2019年5月29日15:25:37
     */
    @Override
    public PageInfo<QuestionModelForHomePage> checkRepeatedQuestionsPageInfo(Integer pageNo, Integer pageSize, String operator, String questionTypeId){

        // 1. 根据题型id获取题型名称
        String questionTypeName = questionTypeService.getById(questionTypeId).getName().trim();
        // 2. 清空此题型的所有的check_result
        questionDao.updateClearCheckResult(operator, questionTypeId);
        // 3. 分题型来进行判断，如果有需要还可以进行拓展
        if ("判断题".contains(questionTypeName) || "单选题".equals(questionTypeName) || "业务选择题".equals(questionTypeName) || "多选题".equals(questionTypeName)) {
            // 判断 (判断题、单选题、多选题) 选项为空
            questionService.checkRadioNullQuestions(operator, questionTypeId);
            //  判断题、单选题、多选题) 选项数量小于4个选项
            questionService.checkRadioNumQuestions(operator, questionTypeId);
            // 判断 (判断题、单选题、多选题)  部分选项重复
            questionService.checkRadioRepeatQuestions(operator, questionTypeId);
            // 判断 (判断题、单选题、多选题)   题干重复
            questionService.checkContentRepeatQuestions(operator, questionTypeId);
        } else {
            // 判断其他题型题干是否重复 （简答题，填空题 等）
            questionService.checkContentRepeatExecptRadioQuestions(operator, questionTypeId);
        }
        // 判断 题干+答案 是否完全相同
        questionService.checkCompleteRepeatQuestions(operator, questionTypeId);
        // 4. 返回查询结果
        PageHelper.startPage(pageNo, pageSize);
        return new PageInfo<QuestionModelForHomePage>(questionDao.checkResult(operator, questionTypeId));

    }



    /**
     * @param operator
     * @param questionTypeId
     * @return java.util.List<com.tfjybj.itoo.exam.model.QuestionModelForHomePage>
     * @Description 检查选项数量
     * @author 刁琳童
     * @since 2.0.0 2019/3/23 14:54
     */
    @Override
    public List<QuestionModelForHomePage> checkRadioNumQuestions(String operator, String questionTypeId) {
        List<QuestionModel> queryCountList = questionDao.queryOptionsNumber(operator, questionTypeId);
        for (QuestionModel model : queryCountList) {
            String id = model.getId();
            String checkResultThird;
            if (model.getCheckResult() == null || "".equals(model.getCheckResult()) || "选项数量小于4项 ".equals(model.getCheckResult())) {
                checkResultThird = "选项数量小于4项 ";
            } else {
                checkResultThird = model.getCheckResult().concat("选项数量小于4项 ");
            }
            questionDao.updateCheckResult(id, checkResultThird);
        }
        return null;
    }

    /**
     * @param operator
     * @param questionTypeId
     * @return java.util.List<com.tfjybj.itoo.exam.model.QuestionModelForHomePage>
     * @Description 检查选项是否为空
     * @author 刁琳童
     * @since 2.0.0 2019/3/23 14:57
     */
    @Override
    public List<QuestionModelForHomePage> checkRadioNullQuestions(String operator, String questionTypeId) {
        List<QuestionModel> queryIsEmptyList = questionDao.queryChoose(operator, questionTypeId);
        for (QuestionModel model : queryIsEmptyList) {
            String id = model.getId();
            String checkResultSecond = model.getCheckResult();
            if (checkResultSecond == null || "".equals(checkResultSecond) || "部分选项为空 ".equals(model.getCheckResult())) {
                checkResultSecond = "部分选项为空 ";
            } else {
                checkResultSecond = model.getCheckResult().concat("部分选项为空 ");
            }
            questionDao.updateCheckResult(id, checkResultSecond);
        }
        return null;
    }

    /**
     * @param operator
     * @param questionTypeId
     * @return java.util.List<com.tfjybj.itoo.exam.model.QuestionModelForHomePage>
     * @Description 检查选项重复
     * @author 刁琳童
     * @since 2.0.0 2019/3/23 14:59
     */
    @Override
    public List<QuestionModelForHomePage> checkRadioRepeatQuestions(String operator, String questionTypeId) {
        List<QuestionModel> queryOptionSameList = questionDao.querySameOptions(operator, questionTypeId);
        for (QuestionModel model : queryOptionSameList) {
            String id = model.getId();
            String checkResultForth;
            if (model.getCheckResult() == null || "".equals(model.getCheckResult()) || "部分选项内容相同 ".equals(model.getCheckResult())) {
                checkResultForth = "部分选项内容相同 ";
            } else {
                checkResultForth = model.getCheckResult().concat("部分选项内容相同 ");
            }
            questionDao.updateCheckResult(id, checkResultForth);
        }
        return null;
    }

    /**
     * @param operator
     * @param questionTypeId
     * @return java.util.List<com.tfjybj.itoo.exam.model.QuestionModelForHomePage>
     * @Description 检查题干重复
     * @author 刁琳童
     * @since 2.0.0 2019/3/23 15:00
     */
    @Override
    public List<QuestionModelForHomePage> checkContentRepeatQuestions(String operator, String questionTypeId) {
        String checkResultFirst;
        // 分组查询 题干重复全部试题
        List<QuestionModel> questionModelListSame = questionDao.checkRepeatedQuestionsContent(operator, questionTypeId);
        for (QuestionModel model : questionModelListSame) {
            String id = model.getId();
            // 题干
            String content = model.getQuestionContent();
            // 试题分类
            String questionClassifyId = model.getQuestionClassifyId();
            // 查询与该题重复的其他试题
            List<QuestionModelForHomePage> models = questionDao.queryByContent(content, operator, questionClassifyId, id);
            for (QuestionModelForHomePage modelForHomePage : models) {
                String newId = modelForHomePage.getId();
                if (modelForHomePage.getCheckResult() == null || "".equals(modelForHomePage.getCheckResult()) || "题干重复 ".equals(modelForHomePage.getCheckResult())) {
                    checkResultFirst = "题干重复 ";
                } else {
                    checkResultFirst = model.getCheckResult().concat("题干重复 ");
                }
                questionDao.updateCheckResult(newId, checkResultFirst);
            }
            // TODO : 去留？。。。
            if (model.getCheckResult() == null || "".equals(model.getCheckResult()) || "题干重复 ".equals(model.getCheckResult())) {
                checkResultFirst = "题干重复 ";
            } else {
                checkResultFirst = model.getCheckResult().concat("题干重复 ");
            }
            questionDao.updateCheckResult( id, checkResultFirst);
        }
        return null;
    }

    /**
     * @param operator
     * @param questionTypeId
     * @return java.util.List<com.tfjybj.itoo.exam.model.QuestionModelForHomePage>
     * @Description 检查单选题、多选题、判断题之外的题干是否重复
     * @author 刁琳童
     * @since 2.0.0 2019/3/23 15:01
     */
    @Override
    public List<QuestionModelForHomePage> checkContentRepeatExecptRadioQuestions(String operator, String questionTypeId) {
        String checkResultFirst = "题干重复";
        List<QuestionModel> questionModelListSame = questionDao.checkRepeatedQuestionsContent(operator, questionTypeId);
        //对其他试题类型中重复的题目进行更新操作
        for (QuestionModel model : questionModelListSame) {
//            String id = model.getId();
//            checkResultFirst = model.getCheckResult().concat("题干重复  ");
            questionDao.checkContentRepeatExecptRadioQuestions(operator, questionTypeId, model.getQuestionContent(), checkResultFirst);
//            questionDao.updateCheckResult(id, checkResultFirst);
        }
        return null;
    }

    /**
     * @param operator       操作人
     * @param questionTypeId 试题类型id
     * @return java.util.List<com.tfjybj.itoo.exam.model.QuestionModelForHomePage>
     * @Description 检查题目是否完全重复，通过题干和答案来判断
     * @author 刁琳童
     * @since 2.0.0 2019/3/24 8:40
     */
    @Override
    public List<QuestionModelForHomePage> checkCompleteRepeatQuestions(String operator, String questionTypeId) {
        String checkResult = "试题重复  ";
        // 1. 查询出来的重复的单个题目
        List<QuestionModel> sameSingleQuestions = questionDao.checkRepeatedQuestions(operator, questionTypeId);
        // 2. 遍历这些题目，然后通过题干和答案在数据库里查询出来并进行更改
        for (QuestionModel question : sameSingleQuestions) {
            questionDao.checkCompleteRepeatQuestions(operator, questionTypeId, question.getQuestionContent(), question.getAnswer(), checkResult);
        }
        return null;
    }


    /**
     * 添加试题
     *
     * @param model 试题集合
     * @return itoo
     * @author 郭凯
     * @since 2.0.0 2018-11-01 08:55:53
     */
    @Override
    public ItooResult createQuestion(@RequestBody List<QuestionAddModel> model) {

        //1、分解题干集合
        List<QuestionAddModel> problemModels = queryProblem(model);
        List<QuestionEntity> questionEntityList = new ArrayList<>();
        List<OptionEntity> optionEntityList = new ArrayList<>();

        //2.获取每个题目的详细信息
        for (QuestionAddModel questionModel : problemModels) {
            QuestionEntity questionEntity = new QuestionEntity();
            BeanUtils.copyProperties(questionModel, questionEntity);

            // 判断是否有父题
            if (org.springframework.util.StringUtils.isEmpty(questionEntity.getParentId())) {
                questionEntity.setParentId(null);
            }
            // 如果Id为空 根据雪花算法生成一个新的Id
            if (org.springframework.util.StringUtils.isEmpty(questionEntity.getId())) {
                questionEntity.setId(IdWorker.getIdStr());
            }
            questionEntityList.add(questionEntity);
            if (questionModel.getOptionModel() != null && questionModel.getOptionModel().size() > 0) {
                if (questionModel.getOptionModel().get(0) == null) {
                    questionModel.setOptionModel(null);
                }
            }
            if (!CollectionUtils.isEmpty(questionModel.getOptionModel())) {
                for (OptionModel optionModel : questionModel.getOptionModel()) {
                    OptionEntity optionEntity = new OptionEntity();
                    BeanUtils.copyProperties(optionModel, optionEntity);
                    optionEntity.setId(IdWorker.getIdStr());
                    optionEntity.setQuestionId(questionModel.getId());
                    optionEntityList.add(optionEntity);
                }
            }

        }
        //3.保存题目和选项信息

        boolean statusMain = questionService.saveBatch(questionEntityList);
        QuestionEntity questionEntity = questionEntityList.get(0);
        boolean statusOption;
        if (CollectionUtils.isEmpty(optionEntityList)) {
            statusOption = true;
        } else {
            statusOption = optionService.saveBatch(optionEntityList);
        }

        if (statusMain && statusOption) {
            boolean flag = onlineExamService.getExamineeStatusChange(questionEntity);
            if (flag) {
                return ItooResult.build(ItooResult.SUCCESS, "您好, 已经将抽到该题的考生的错题修改, 请您通知考生刷新界面即可", true);
            } else {
                return ItooResult.build(ItooResult.SUCCESS, "", true);
            }

        } else {
            return ItooResult.build(ItooResult.FAIL, "题目保存失败", false);
        }

    }

    /**
     * 删除单个试题
     *
     * @param id 试题id
     * @return ItooResult
     * @author 郭凯
     * @since 2.0.0 2018年11月9日16:40:36
     */
    @Override
    public boolean updateIsDelete(String id) {
        return questionDao.updateIsDelete(id);
    }

    /**
     * 更新试题检查结果
     *
     * @param id          试题id
     * @param checkResult 试题检查结果
     * @return Boolean
     * @author 郭凯
     * @since 2.0.0 2018-11-8 15:48:01
     */
    @Override
    public boolean updateCheckResult(String id, String checkResult) {
        return questionDao.updateCheckResult(id, checkResult);
    }


    /**
     * 查询试题类型名称
     *
     * @param operator       操作人
     * @param questionTypeId 试题类型id
     * @return List
     * @author 郭凯
     * @since 2.0.0 2018-11-8 15:48:01
     */
    @Override
    public List<QueryQuestionTypeModel> queryQuestionTypeName(String operator, String questionTypeId) {
        QuestionEntity questionEntity = new QuestionEntity();

        List<QueryQuestionTypeModel> queryQuestionTypeModelList = new ArrayList<>();
        questionEntity.setOperator(operator);
        questionEntity.setQuestionTypeId(questionTypeId);
        List<QueryQuestionModel> queryQuestionModelList = questionDao.queryByEntity(questionEntity);
        for (QueryQuestionModel model : queryQuestionModelList) {
            QueryQuestionTypeModel queryQuestionTypeModel = new QueryQuestionTypeModel();
            String classifyId = model.getQuestionClassifyId();
            String classifyName = questionDao.queryQuestionClassifyName(classifyId);
            if (classifyName != null && !"".equals(classifyName)) {
                BeanUtils.copyProperties(model, queryQuestionTypeModel);
                queryQuestionTypeModel.setQueryQuestionClassifyName(classifyName);
                queryQuestionTypeModelList.add(queryQuestionTypeModel);
            }
        }
        return queryQuestionTypeModelList;
    }


    /**
     * 查询试题类型名称
     *
     * @param courseId 课程id
     * @return List
     * @author 任蒙蒙
     * @since 2.0.0 2018-12-1 15:48:01
     */
    @Override
    public List<QuestionMainModel> queryAllProblemByCourseId(String courseId, String operator) {
        return questionDao.selectQuestionByCourseId(courseId, operator);
    }


    /**
     * 查询必抽题父题对应的子题（混合题用）
     *
     * @param parentId 父题干id
     * @return List
     * @author 任蒙蒙
     * @since 2.0.0 2018-12-16 11:23:01
     */
    @Override
    public List<QuestionMainModel> selectSubQuestionByParentId(String parentId) {
        return questionDao.selectSubQuestionByParentId(parentId);
    }


    /**
     * 查询试题类型名称
     *
     * @param questionTypeId     题型id
     * @param operator           操作人
     * @param questionClassifyId 试题分类id
     * @return List
     * @author 杨海云
     * @since 2.0.0 2018-12-1 15:48:01
     */
    @Override
    public List<QuestionModel> queryQuestionDegree(String questionTypeId, String operator, String courseId, String
            questionClassifyId) {
        return questionDao.queryQuestionDegree(questionTypeId, operator, courseId, questionClassifyId);
    }

    /**
     * 根据操作人和课程id查询试题分类
     *
     * @param operator 操作人
     * @param courseId 课程id
     * @return List
     * @author 郭凯
     * @since 2.0.0 2018-12-1 15:48:01
     */
    @Override
    public List<String> queryQuestionClassifyType(String operator, String courseId) {
        return questionDao.queryQuestionClassifyType(operator, courseId);
    }


    /**
     * 分页根据试题内容模糊查询question
     *
     * @param content 试题内容
     * @return 模糊查询的question
     * @author 郭凯
     * @since 2.0.0 2018-11-01 08:55:53
     */
    @Override
    public PageInfo<QuestionModelForHomePage> queryByLikeContent(String content, String operator, Integer
            pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<QuestionModelForHomePage> questionModelList = questionDao.queryByLikeContent(content, operator);
        return new PageInfo<>(questionModelList);
    }

    /**
     * 根据id查找Question
     *
     * @param id 主键id
     * @return 根据id查找Question
     * @author 郭凯
     * @since 2.0.0 2018-12-1 15:53:12
     */
    @Override
    public QuestionAddModel queryById(String id) {
        Integer flag = questionDao.queryById(id);
        if (flag == 1) {
            return null;
        } else {
            QuestionEntity questionEntity = questionDao.selectById(id);
            QuestionAddModel questionModel = new QuestionAddModel();
//            String content = convertToString(questionEntity.getQuestionContentHtml());
            String content = questionEntity.getQuestionContentHtml();
//            String answer = convertToString(questionEntity.getAnswerHtml());
            String answer = questionEntity.getAnswerHtml();
            BeanUtils.copyProperties(questionEntity, questionModel);
//            String analysis = null;
            if (questionEntity.getAnalysisHtml() != null) {
//                try {
//                    analysis = new String(questionEntity.getAnalysisHtml(),"UTF-8");
//                } catch (UnsupportedEncodingException e) {
//                    log.error("字符转换错误", e);
//                }
                String analysis = questionEntity.getAnalysisHtml();
                questionModel.setAnalysisHtml(analysis);
            } else {
                questionModel.setAnalysisHtml("");
            }
            questionModel.setQuestionContentHtml(content);
            questionModel.setAnswerHtml(answer);
            List<QuestionAddModel> questionAddModelList = new ArrayList<>();
            List<QuestionEntity> questionEntityList = questionDao.getByParentId(id);
            for (QuestionEntity entity : questionEntityList) {
                QuestionAddModel questionAddModel = new QuestionAddModel();
                BeanUtils.copyProperties(entity, questionAddModel);
//                String questionContent = convertToString(entity.getQuestionContentHtml());
                String questionContent = entity.getQuestionContentHtml();
//                String questionAnswer = convertToString(entity.getAnswerHtml());
                String questionAnswer = entity.getAnswerHtml();
                questionAddModel.setQuestionContentHtml(questionContent);
                questionAddModel.setAnswerHtml(questionAnswer);
//                String questionAnalysis;
                if (questionEntity.getAnalysisHtml() != null) {
//                    questionAnalysis = convertToString(questionEntity.getAnalysisHtml());
                    String questionAnalysis = entity.getAnalysisHtml();
                    questionAddModel.setAnalysisHtml(questionAnalysis);
                } else {
                    questionAddModel.setAnalysisHtml("");
                }
                questionAddModelList.add(questionAddModel);
            }
            questionModel.setQuestionModel(questionAddModelList);
            return questionModel;
        }
    }

    /**
     * 将byte类型的HTML转成String类型HTML
     *
     * @param contentHtml byte类型HTML
     * @return String String类型的HTML
     * @author 郭凯
     * @since 2.0.0 2018-12-1 15:53:12
     */
    private String convertToString(byte[] contentHtml) {
        String content = null;
        try {
            content = new String(contentHtml, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            log.error("字符转换错误", e);
        }
        return content;
    }

    @Override
    public List<QuestionMainModel> selectQuestionByParentId(String courseId, String operator) {
        return questionDao.selectQuestionByParentId(courseId, operator);
    }


    /**
     * 设置必抽题
     *
     * @param operator       操作人
     * @param courseId       课程id
     * @param questionTypeId 题型id
     * @return 根据id查找Question
     * @author 郭凯
     * @since 2.0.0  2018-12-8 10:27:31
     */
    @Override
    public List<QueryQuestionModel> queryMustSelect(String operator, String courseId, String questionTypeId) {
        return questionDao.queryMustSelect(operator, courseId, questionTypeId);
    }


    /**
     * 指导入试题
     *
     * @param multipartFile 传入的文件
     * @param request       http请求
     * @param response      http返回
     * @param quesTypeId    试题类型id
     * @param quesName      试题类型名称
     * @param courseId      课程id
     * @return ITooResult
     * @author 侯旭日 郭凯  杜雨
     * @since 2.0.0 2018-11-28 19:40:28
     */
    @Transactional(rollbackOn = Exception.class)
    @Override
    public ItooResult importTemplate(MultipartFile multipartFile, HttpServletRequest request, HttpServletResponse
            response, String quesTypeId, String quesName, String courseId, String operator) {
        response.setContentType("UTF-8");

        //存入失败的集合和个数
        Map<Integer, QuestionTemplate> failAgre = new HashMap<>();
        int failLog = 0;
        String errorList = IdWorker.getIdStr();
        Long size = redisTemplate.opsForZSet().size(errorList);
        size = size == null ? 0L : size;
        try {
            //获取文件名
            String fileName = multipartFile.getOriginalFilename();
            //校验文件是否存在
            if (fileName == null) {
                log.error("导入失败,fileName is null!");
                return ItooResult.build(ItooResult.FAIL, "传入的文件为空！");
            }
            //EXCEL解析成List
            Map<Serializable, Serializable> map = new HashMap<>(4);
            map.put("sheetName", quesName);
            map.put("Class", QuestionTemplate.class);
            List<QuestionTemplate> questionTemplates = ExcelUtil.importExcel(Objects.requireNonNull(fileName), map, request, response);

            if (questionTemplates.size() == 0) {
                return ItooResult.build(ItooResult.FAIL, "导入的数据为空，请填写！");
            }

            QuestionEntity questionEntity = new QuestionEntity();
            //optionCount个数默认为1，其他题型重新设置
            questionEntity.setOptionCount(1);
            String classifyIdFirst;
            String classifyIdSecond = null;

            for (QuestionTemplate questionTemplate : questionTemplates) {
                classifyIdSecond = null;
                //查询一级分类名称
                // 如果Excel中分类为空，默认为“期末”
                if (StringUtils.isEmpty(questionTemplate.getQuestionClassify())) {
                    //根据coruse和level=1查询一级目录
                    List<QuestionClassifyEntity> questionClassifyEntityList = questionClassifyService.queryByCourseId(courseId);
                    //如果没有一级目录记录，需要插入一级目录
                    if(CollectionUtils.isEmpty(questionClassifyEntityList)){
                       //默认期末
                        String neme = "期末";
                        String parentIdd = "";
                        classifyIdFirst = creatClassify(neme,courseId,operator,1,parentIdd);
                    }else{
                        classifyIdFirst = questionClassifyEntityList.get(0).getId();
                    }
                } else {//否则，Excel中分类不为空，根据分类名称，课程Id，操作人查找相应的分类Id
                    String name = questionTemplate.getQuestionClassify();
                    QuestionClassifyEntity classifyEntity = questionClassifyService.getByName(name, courseId, operator);
                    //questionClassifyEntityList 判空
                    if(null==classifyEntity){
                        String parentIdd = "";
                        classifyIdFirst = creatClassify(name,courseId,operator,1,parentIdd);
                    }else{
                        classifyIdFirst = classifyEntity.getId();
                    }
                }
                if(classifyIdFirst == null){
                    return ItooResult.build(ItooResult.FAIL, "一级目录不存在，请核查！");
                }

                //获取二级分类-章节
                String chapter = questionTemplate.getChapter();
                //根据章节、课程Id获取章节列表（包含期末/随堂小练 第一章。）
                List<QuestionClassifyEntity> classifyEntityList = questionClassifyService.getByChapter(chapter, courseId);
                //如果根据二级目录章节查出来的父id和根据一级目录查出来的父id不一致，就得重新插入二级目录-章节
                for (QuestionClassifyEntity classify : classifyEntityList) {
                    //如果父级别相同，获取章节Id
                    if (classify.getParentId().equals(classifyIdFirst)) {
                        classifyIdSecond = classify.getId();
                    }
                }
                //章节不存在，插入二级目录章节
                if (classifyIdSecond == null){
                    classifyIdSecond = creatClassify(chapter,courseId,operator,2,classifyIdFirst);
                    if(classifyIdSecond == null){
                        return ItooResult.build(ItooResult.FAIL, "二级目录不存在，请核查！");
                    }
                }
                //判断题试题是否重复
                boolean flag=this.checkCompleteQuestions(questionTemplate,courseId,quesTypeId,classifyIdSecond);
                if(flag){
                    //存入失败的集合和个数
                    failLog++;
                    questionTemplate.setFailReason("试题重复！");
                    failAgre.put(failLog, questionTemplate);
                    redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                    continue;
                }

                // 校验试题编号是否重复
                List<QuestionEntity> list = checkSerial(questionTemplate.getSerial(),operator);
                if(CollectionUtils.isNotEmpty(list)){
                    //存入失败的集合和个数
                    failLog++;
                    questionTemplate.setFailReason("试题编号重复！");
                    failAgre.put(failLog, questionTemplate);
                    redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                    continue;
                }

                //主题干不能为空
                if (StringUtils.isEmpty(questionTemplate.getQuestionContent())) {
                    //存入失败的集合和个数
                    failLog++;
                    questionTemplate.setFailReason("主题干不能为空！");
                    failAgre.put(failLog, questionTemplate);
                    redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                    continue;
                }

                questionEntity.setId(IdWorker.getIdStr());
                questionEntity.setOperator(operator);
                questionEntity.setVersion(0);
                //获取题干
                questionEntity.setQuestionContent(questionTemplate.getQuestionContent());
//                questionEntity.setQuestionContentHtml(("<p>" + questionTemplate.getQuestionContent() + "</p>").getBytes("UTF-8"));
                questionEntity.setQuestionContentHtml(("<p>" + questionTemplate.getQuestionContent() + "</p>"));
                questionEntity.setAnalysis("");
                questionEntity.setAnalysisHtml(null);
                questionEntity.setCheckStatus(0);
                questionEntity.setDegreeStatistic(0);
                questionEntity.setKnowledgePoint("");
                try {
                    //转换题号和难度等级，将文本型数字转换为Integer类型数字
                    questionEntity.setSerial(Integer.parseInt(questionTemplate.getSerial()));
                    questionEntity.setDegreeInitial(Integer.parseInt(questionTemplate.getDegreeInitial()));
                } catch (Exception ex) {
                    log.error("试题题号、难度类型转换失败：{}",ex.getMessage());

                    //存入失败的集合和个数
                    failLog++;
                    questionTemplate.setFailReason("题号、难度等级必须为数字！");
                    failAgre.put(failLog, questionTemplate);
                    redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                    continue;
                }
                //获取题型Id
                questionEntity.setQuestionTypeId(quesTypeId);
                //获取分类Id
                questionEntity.setQuestionClassifyId(classifyIdSecond);
                //获取课程Id
                questionEntity.setCourseId(courseId);

                //标准答案不能为空
                if (StringUtils.isEmpty(questionTemplate.getStandardAnswer())) {
                    //存入失败的集合和个数
                    failLog++;
                    questionTemplate.setFailReason("标准答案不能为空！");
                    failAgre.put(failLog, questionTemplate);
                    redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                    continue;
                }
                questionEntity.setAnswer(questionTemplate.getStandardAnswer());
//                questionEntity.setAnswerHtml(("<p>" + questionTemplate.getStandardAnswer() + "</p>").getBytes("UTF-8"));
                questionEntity.setAnswerHtml("<p>" + questionTemplate.getStandardAnswer() + "</p>");
                //获取录入试题来源 0-手工,1-excel导入,2-word导入
                questionEntity.setSource(1);
                //是否有效，除了F全是有效
                if ("f".equalsIgnoreCase(questionTemplate.getIsEffective())) {
                    questionEntity.setIsEffective(1);
                } else {
                    questionEntity.setIsEffective(0);
                }
                //简答、名词解释、判断题为一类题型，也是所有题型共有属性


                //判断题答案是否有效，规定：对 错
                if ("判断题".equals(quesName)) {
                    //选项个数设置为2
                    questionEntity.setOptionCount(2);
                    //实例化一个存放“对”的选项实体
                    OptionEntity optionEntity = new OptionEntity();
                    //实例化一个存放“错”的选项实体
                    OptionEntity option = new OptionEntity();
                    optionEntity.setId(IdWorker.getIdStr());
                    optionEntity.setOptionOrder(1);
                    optionEntity.setOperator(operator);
                    optionEntity.setQuestionId(questionEntity.getId());
                    optionEntity.setOptionName("对");
//                    optionEntity.setOptionNameHtml(("<p>对</p>").getBytes("UTF-8"));
                    optionEntity.setOptionNameHtml(("<p>对</p>"));


                    option.setId(IdWorker.getIdStr());
                    option.setOptionOrder(2);
                    option.setOperator(operator);
                    option.setQuestionId(questionEntity.getId());
                    option.setOptionName("错");
//                    option.setOptionNameHtml(("<p>错</p>").getBytes("UTF-8"));
                    optionEntity.setOptionNameHtml(("<p>错</p>"));

                    if (!("对".equals(questionTemplate.getStandardAnswer()) || "错".equals(questionTemplate.getStandardAnswer()))) {
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("答案不合法！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                    // 存入正确答案的选项
                    optionService.save(optionEntity);
                    // 存入错误答案的选项
                    optionService.save(option);
                }
                //单选题
                if ("单选题".equals(quesName) || "多选题".equals(quesName) || "业务选择题".equals(quesName)|| "计算选择题".equals(quesName)) {
                    questionEntity.setId(IdWorker.getIdStr());
                    questionEntity.setOptionCount(4);
                    //标准答案
                    String answer;
                    boolean logOpera = false;
                    StringBuilder answerBuilder = new StringBuilder();


                    // 判断选项是否在规定的范围之内 否则改题 导入失败
                    for (int i = 0; i < questionTemplate.getStandardAnswer().length(); i++) {
                        //判断选项是否为ABCD
                        String allAnswer = questionTemplate.getStandardAnswer();
                        String opera = allAnswer.substring(i, i + 1);
                        if (!("a".equalsIgnoreCase(opera) || "b".equalsIgnoreCase(opera) || "c".equalsIgnoreCase(opera) || "d".equalsIgnoreCase(opera) || "e".equalsIgnoreCase(opera))) {
                            logOpera = true;
                            break;
                        }

                        if (("单选题".equals(quesName) && "e".equalsIgnoreCase(opera))) {
                            logOpera = true;
                            break;
                        }
                        if (("计算选择题".equals(quesName) && "e".equalsIgnoreCase(opera))) {
                            logOpera = true;
                            break;
                        }
                        if (("业务选择题".equals(quesName) && "e".equalsIgnoreCase(opera))) {
                            logOpera = true;
                            break;
                        }
                        //存放答案内容，不是选项
                        if ("a".equalsIgnoreCase(opera)) {
                            answerBuilder.append(questionTemplate.getAnswerA()).append("|");
                        }
                        if ("b".equalsIgnoreCase(opera)) {
                            answerBuilder.append(questionTemplate.getAnswerB()).append("|");
                        }
                        if ("c".equalsIgnoreCase(opera)) {
                            answerBuilder.append(questionTemplate.getAnswerC()).append("|");
                        }
                        if ("d".equalsIgnoreCase(opera)) {
                            answerBuilder.append(questionTemplate.getAnswerD()).append("|");
                        }
                        if ("e".equalsIgnoreCase(opera)) {
                            answerBuilder.append(questionTemplate.getAnswerE()).append("|");
                        }
                    }
                    answer = answerBuilder.toString();
                    if (logOpera) {
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("答案不合法！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                    //截取答案最后一个“|”
                    questionEntity.setAnswer(answer.substring(0, answer.length() - 1));
                    questionEntity.setOptionCount(4);
                    //向选项表里插入数据
                    //选项A
                    OptionEntity optionEntity = new OptionEntity();
                    optionEntity.setId(IdWorker.getIdStr());
                    optionEntity.setOperator(operator);
                    optionEntity.setOptionOrder(1);
                    //选项内容不能为空
                    if (StringUtils.isEmpty(questionTemplate.getAnswerA())) {
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("选项内容不能为空！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                    optionEntity.setOptionName(questionTemplate.getAnswerA());
//                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerA() + "</p>").getBytes("UTF-8"));
                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerA() + "</p>"));
                    optionEntity.setQuestionId(questionEntity.getId());
                    System.out.println(optionEntity);
                    optionService.save(optionEntity);
                    //选项B
                    optionEntity.setId(IdWorker.getIdStr());
                    optionEntity.setOptionOrder(2);
                    //选项内容不能为空
                    if (StringUtils.isEmpty(questionTemplate.getAnswerB())) {
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("选项内容不能为空！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                    optionEntity.setOptionName(questionTemplate.getAnswerB());
//                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerB() + "</p>").getBytes("UTF-8"));
                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerB() + "</p>"));
                    optionEntity.setQuestionId(questionEntity.getId());
                    System.out.println(optionEntity);
                    optionService.save(optionEntity);
                    //选项C
                    optionEntity.setId(IdWorker.getIdStr());
                    optionEntity.setOptionOrder(3);
                    //选项内容不能为空
                    if (StringUtils.isEmpty(questionTemplate.getAnswerC())) {
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("选项内容不能为空！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                    optionEntity.setOptionName(questionTemplate.getAnswerC());
//                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerC() + "</p>").getBytes("UTF-8"));
                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerC() + "</p>"));
                    optionEntity.setQuestionId(questionEntity.getId());
                    System.out.println(optionEntity);
                    optionService.save(optionEntity);
                    //选项D
                    optionEntity.setId(IdWorker.getIdStr());
                    optionEntity.setOptionOrder(4);
                    //选项内容不能为空
                    if (StringUtils.isEmpty(questionTemplate.getAnswerD())) {
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("选项内容不能为空！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                    optionEntity.setOptionName(questionTemplate.getAnswerD());
//                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerD() + "</p>").getBytes("UTF-8"));
                    optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerD() + "</p>"));
                    optionEntity.setQuestionId(questionEntity.getId());
                    System.out.println(optionEntity);
                    optionService.save(optionEntity);
                    if ("多选题".equals(quesName)) {
                        //多选题选项个数为4
                        questionEntity.setOptionCount(4);
                        //选项E
                        if (!(StringUtils.isEmpty(questionTemplate.getAnswerE()))) {
                            optionEntity.setId(IdWorker.getIdStr());
                            optionEntity.setOptionOrder(5);
                            optionEntity.setOptionName(questionTemplate.getAnswerE());
//                            optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerE() + "</p>").getBytes("UTF-8"));
                            optionEntity.setOptionNameHtml(("<p>" + questionTemplate.getAnswerE() + "</p>"));
                            optionEntity.setQuestionId(questionEntity.getId());
                            System.out.println(optionEntity);
                            optionService.save(optionEntity);
                            //选项E存在，选项个数设置为5
                            questionEntity.setOptionCount(5);
                        }
                    }
                }
                //填空题

                if ("填空题".equals(quesName)) {
                    //填空个数
                    try {
                        questionEntity.setOptionCount(Integer.parseInt(questionTemplate.getOptionCount()));
                    } catch (Exception ex) {
                        log.error("填空题空数类型转换失败：{}",ex.getMessage());
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("空数必须为数字！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                    //是否别名
                    if ("t".equalsIgnoreCase(questionTemplate.getIsAlias())) {
                        questionEntity.setIsAlias(1);
                    } else {
                        questionEntity.setIsAlias(0);
                    }
                    //是否乱序
                    if ("f".equalsIgnoreCase(questionTemplate.getIsOutOfOrder())) {
                        questionEntity.setIsOutOfOrder(1);
                    } else {
                        questionEntity.setIsOutOfOrder(0);
                    }
                    //标准答案，每个答案之前用|分隔，每个别名之间
                    String[] split = questionTemplate.getStandardAnswer().split("\\|");
                    //判断空数是否和答案一致
                    if (questionEntity.getOptionCount() == split.length) {
                        //判断是否有别名，没别名 但答案字段设置别名即失败
                        if (questionEntity.getIsAlias() == 0 && questionTemplate.getStandardAnswer().split("@#").length > 1) {
                            //提示未设置别名，但输入了别名
                            failLog++;
                            questionTemplate.setFailReason("提示未设置别名，但输入了别名，请修改设置！");
                            failAgre.put(failLog, questionTemplate);
                            redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                            continue;
                        } else {
                            questionEntity.setAnswer(questionTemplate.getStandardAnswer());
                        }
                    } else {
                        //存入失败的集合和个数
                        failLog++;
                        questionTemplate.setFailReason("空数必须和答案一致！");
                        failAgre.put(failLog, questionTemplate);
                        redisTemplate.opsForZSet().add(errorList, questionTemplate, size + 1);
                        continue;
                    }
                }
                System.out.println(questionEntity);
                questionService.save(questionEntity);
            }
        } catch (Exception ex) {
            log.error("导入数据异常：{}",ex.getMessage());
            return ItooResult.build(ItooResult.FAIL, "导入数据异常！", ex);
        }
        if (failLog == 0) {
            return ItooResult.build(ItooResult.SUCCESS, "导入成功！");
        }
        return ItooResult.build("0001", "导入部分成功！", errorList);

    }


    /**
     * 导出导入异常的试题
     *
     * @param errorListId 异常题型key
     * @param response    导出请求
     * @return boolean
     * @author 李娜
     */
    @Override
    public boolean exportErrorList(String errorListId, HttpServletResponse response) {
        //从redis取出没有导入成功的试题
        Set<QuestionTemplate> set = redisTemplate.opsForZSet().range(errorListId, 0, -1);
        if (set == null || set.isEmpty()) {
            return false;
        }
        List<QuestionTemplate> questionTemplates = new ArrayList<>(set);

        //清空redis
        redisTemplate.delete(errorListId);

        //导出
        if (questionTemplates.size() == 0) {
            return false;
        }

        Map<Serializable, Serializable> errorMap = new HashMap<>();
        errorMap.put("name", "未导入的信息");
        errorMap.put("sheetName", " quesName");
        errorMap.put("title", "未导入的信息");
        errorMap.put("columns", new String[]{"questionContent", "failReason"});
        errorMap.put("dataList", (Serializable) questionTemplates);
        try {
            ExcelUtil.exportExcel(errorMap, response);
        } catch (Exception e) {

            return false;
        }
        return true;
    }

    /**
     * 根据操作人查询题型类型
     *
     * @param operator 操作者
     * @return 根据操作人查询题型类型
     * @author 贾建清
     * @since 2.0.0 2018-12-13 16:02:36
     */
    @Override
    public List<OperatorQuestionModel> queryQuestionType(String operator) {
        return questionDao.queryQuestionType(operator);
    }


    /**
     * 根据操作人和题型类型查询试题
     *
     * @param operator       操作员
     * @param questionTypeId 题型id
     * @return 根据操作人和题型类型查询试题
     * @author 贾建清
     * @since 2.0.0 2018-12-13 17:46:44
     */
    @Override
    public PageInfo<QuestionModel> queryQuestion(String operator, String[] questionTypeId, Integer pageNo, Integer
            pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<QuestionModel> questionModelList = questionDao.queryQuestion(operator, questionTypeId);
        return new PageInfo<>(questionModelList);
    }

    /**
     * question_Classify 模糊查询必抽题
     *
     * @param searchInput    查询内容
     * @param courseId       课程id
     * @param questionTypeId 题型id
     * @param operator       操作人
     * @author 杨海云
     * @since 2.0.0 2018-12-5 13:27:08
     */
    @Override
    public PageInfo<QuestionModel> indistinctQuestionClassify(String searchInput, String courseId, String
            questionTypeId, String operator) {

        return new PageInfo<>(questionDao.indistinctQuestionClassify(searchInput, courseId, questionTypeId, operator));
    }


    /**
     * 根据课程/试题题型/分类查询试题
     *
     * @param questionEntity 试题实体
     * @param pageNo         页码
     * @param pageSize       页数
     * @return ItooResult 根据课程/试题题型/分类查询试题
     * @author 贾建清
     * @since 2.0.0 2018-12-16 14:55:14
     */
    @Override
    public PageInfo<QuestionModelForHomePage> queryQuestionByType(QuestionEntity questionEntity, Integer
            pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<QuestionModelForHomePage> questionModelList = questionDao.queryQuestionByType(questionEntity);
        return new PageInfo<>(questionModelList);
    }

    /**
     * 根据课程id查询课程类型
     *
     * @param courseId
     * @return
     * @author 李娜
     */
    @Override
    public List<QuestionTypeModel> queryQuestionTypeByCourse(@Param("courseId") String courseId) {
        return questionDao.queryQuestionTypeByCourse(courseId);
    }

    @Override
    public List<QuestionEntity> selectQuestionByCourse(String courseId){
        return questionDao.selectQuestionByCourse(courseId);
    }

    /**
     * 删除单个试题方法
     *
     * @param questionId 试题id
     * @author 李娜
     */
    @Transactional(rollbackOn = Exception.class)
    public void deleteQuestion(String questionId) {
        //根据试题id查询该试题是否有选项
        List<String> options = questionDao.selectOptionByQuestionId(questionId);
        //无选项,分为无子题无选项和有子题无选项
        if (CollectionUtils.isEmpty(options)) {
            //直接删除父题
            questionDao.deleteQuestionById(questionId);

            //根据questionId父题查询子题id
            List<QuestionModel> questionChild = questionDao.queryQuestionById(questionId);
            //如果子题不为空，则删除子题和选项
            if (!CollectionUtils.isEmpty(questionChild)) {
                //删除子题
                questionDao.deleteQuestionByParentId(questionId);
                //根据子题查询选项
                List<String> optionList = new ArrayList<>();
                for (QuestionModel questionModel : questionChild) {
                    List<String> option = questionDao.selectOptionByQuestionId(questionModel.getId());
                    if (!CollectionUtils.isEmpty(option)) {
                        optionList.addAll(option);
                    }
                }
                //删除子题选项
                if (!CollectionUtils.isEmpty(optionList)) {
                    questionDao.deleteOption(optionList);
                }
            }
        } else {
            //删除试题，删除选项
            //直接删除父题
            questionDao.deleteQuestionById(questionId);
            //删除选项
            questionDao.deleteOptionByQuestionId(questionId);
        }
    }

    /**
     * 批量删除试题
     *
     * @param questionIds 试题id
     * @author 李娜
     * @since 2018年12月18日14点55分
     */
    @Override
    public void deleteQuestionBatch(List<String> questionIds) {
        for (String questionId : questionIds) {
            deleteQuestion(questionId);
        }
    }

    /**
     * 检查json格式是否正确
     *
     * @param courseId       课程id
     * @param questionTypeId 题型id
     * @return ItooResult
     * @author 郭凯
     * @since 2.0.0  2019-1-16 15:14:38
     */
    @Override
    public ItooResult checkJSON(String courseId, String questionTypeId) {
        List<QuestionEntity> questionEntityList = questionDao.queryByCourseId(courseId, questionTypeId);
        List<String> ids = new ArrayList<>();

        for (QuestionEntity entity : questionEntityList) {
            try {
                List<BussinessAllModel> bussinessAllModelList = JacksonJsonUntil.jsonToList(entity.getAnswer(), BussinessAllModel.class);
            } catch (IOException e) {
                ids.add(entity.getId());
                e.printStackTrace();
            }
        }
        for (String questionId : ids) {
            String remark = "JSON转换失败";
            questionDao.updateRemark(questionId, remark);
        }
        return ItooResult.build(ItooResult.SUCCESS, "查询成功");
    }

    /**
     * 根据旧题的Id查询旧题题干内容
     *
     * @param oldQuestionId 旧题 Id
     * @return oldQuesitonContent 旧题题干内容
     * @author 任蒙蒙
     * @since 2.0.0 2018-11-17 17:10:28
     */
    @Override
    public String selectOldQuestion(String oldQuestionId) {
        return questionDao.selectOldQuestion(oldQuestionId);
    }

    /**
     * 根据新题的Id查询新题的model
     *
     * @param newQuestionId 新题Id
     * @return List
     * @author 任蒙蒙
     * @since 2.0.0 2018-12-29 10:10:01
     */
    @Override
    public QuestionMainModel selectNewQuestionModel(String newQuestionId) {
        return questionDao.selectNewQuestionModel(newQuestionId);
    }

    /**
     * 根据旧题id查询新题id
     *
     * @param questionId 旧题id
     * @return ItooResult
     * @author 郭凯
     * @since 2.0.0  2019-1-16 15:14:38
     */
    @Override
    public List<QuestionEntity> selectNewQuestionById(String questionId) {
        List<QuestionEntity> questionEntity = questionDao.selectNewQuestionById(questionId);
        if (questionEntity == null || questionEntity.size() <= 0) {
            log.info("题库中没有该试题（包括已删除试题）!");
            return null;
        }
        if (questionEntity.get(0).getIsDelete() == 1) {
            String quesID = questionEntity.get(0).getId();
            while (true) {
                List<QuestionEntity> questionEntity2 = questionDao.selectNewQuestionByHisId(quesID);
                if (questionEntity2 == null || questionEntity2.size() <= 0) {
                    log.warn("没有通过历史ID找到试题，该试题ID为：{}", quesID);
                    return questionEntity2;
                }
                if (questionEntity2.get(0).getIsDelete() == 1) {
                    quesID = questionEntity2.get(0).getId();
                } else {
                    return questionEntity2;
                }
            }
        } else {
            return questionEntity;
        }
//        while(true){
////            QuestionEntity questionEntity1 =new QuestionEntity();
//            QuestionEntity questionEntity1 = questionDao.selectNewQuestionById(questionId);
//            if (questionEntity1.getIsDelete()==1){
//                QuestionEntity questionEntity2 = questionDao.selectNewQuestionByHisId(questionEntity1.getId());
//            }
//        }


    }

    /**
     * 根据课程id,题型id,章节id筛选题
     *
     * @param courseId           课程id
     * @param questionTypeId     试卷类型id
     * @param questionClassifyId 试卷分类
     * @param operator           登录人
     * @return 符合筛选条件的集合
     * @author 马莹
     * @since 2019-1-31 10:09:00
     */
    @Override
    public List<QuestionMainModel> selectQuestion(String courseId, String questionTypeId, String
            questionClassifyId, String operator) {
        return questionDao.selectQuestion(courseId, questionTypeId, questionClassifyId, operator);
    }

    /**
     * 题库检查点: 检查重复试题编号
     *
     * @param serial       String
     * @return List
     * @author duyu
     * @since 2019年5月26日11:26:32
     */
    @Override
    public List<QuestionEntity> checkSerial(String serial, String operator){
        return questionDao.checkSerial(serial,operator);
    }


    /**
     *  新增根节点或一级节点或二级节点
     * @param name 一级目录或二级目录
     * @param courseId 课程id
     * @param operator 操作者
     * @param level 1为一级目录，2位二级目录
     * @param parentId 父id
     * @return 一级目录id或二级目录id
     */
    private String creatClassify(String name,String courseId,String operator,Integer level,String parentId){
        String id = null;
        if(courseId == null || operator == null || name == null){
            log.info("自动插入试题目录时，课程id：{}或操作者：{}为空或目录名称：{}" + courseId,operator,name);
            return id;
        }
        if(level == 1){
            //查询根目录是否存在
            QuestionClassifyEntity questionClassifyEntity = questionClassifyService.queryByCourseIdAndLevel(courseId,operator);
            //如果根目录不存在，需要先插入根目录
            if(questionClassifyEntity == null){
                QuestionClassifyEntity questionClassifyEntity1= new QuestionClassifyEntity();
                questionClassifyEntity1.setName("试题分类");
                questionClassifyEntity1.setParentId("0");
                questionClassifyEntity1.setCourseId(courseId);
                questionClassifyEntity1.setQuestionCount(0);
                questionClassifyEntity1.setLevel(0);
                questionClassifyEntity1.setOperator(operator);
                questionClassifyService.save(questionClassifyEntity1);

                String id1 = questionClassifyService.queryByCourseIdAndLevel(courseId,operator).getId();
                QuestionClassifyEntity questionClassifyEntity2= new QuestionClassifyEntity();
                questionClassifyEntity2.setName(name);
                questionClassifyEntity2.setParentId(id1);
                questionClassifyEntity2.setCourseId(courseId);
                questionClassifyEntity2.setQuestionCount(0);
                questionClassifyEntity2.setLevel(1);
                questionClassifyEntity2.setOperator(operator);
                questionClassifyService.save(questionClassifyEntity2);

                QuestionClassifyEntity classifyEntity = questionClassifyService.getByName(name, courseId, operator);
                id = classifyEntity.getId();
            } else {
                //如果根目录存在，只需要插入一级目录即可
                QuestionClassifyEntity questionClassifyEntity3= new QuestionClassifyEntity();
                questionClassifyEntity3.setName(name);
                questionClassifyEntity3.setParentId(questionClassifyEntity.getId());
                questionClassifyEntity3.setCourseId(courseId);
                questionClassifyEntity3.setQuestionCount(0);
                questionClassifyEntity3.setLevel(1);
                questionClassifyEntity3.setOperator(operator);
                questionClassifyEntity3.setId(IdWorker.getIdStr());
                questionClassifyService.save(questionClassifyEntity3);

                QuestionClassifyEntity classifyEntity = questionClassifyService.getByName(name, courseId, operator);
                id = classifyEntity.getId();
            }
        }else {
            if(parentId == null){
                log.info("自动插入试题目录时，一级目录不存在，parentId：{}" + parentId);
                return id;
            }
            //插入二级目录
            QuestionClassifyEntity questionClassifyEntity = new QuestionClassifyEntity();
            questionClassifyEntity.setId(IdWorker.getIdStr());
            questionClassifyEntity.setName(name);
            questionClassifyEntity.setParentId(parentId);
            questionClassifyEntity.setCourseId(courseId);
            questionClassifyEntity.setQuestionCount(0);
            questionClassifyEntity.setLevel(2);
            questionClassifyEntity.setOperator(operator);
            questionClassifyService.save(questionClassifyEntity);

            QuestionClassifyEntity classifyEntity = questionClassifyService.getByName(name, courseId, operator);
            id = classifyEntity.getId();
        }
        return id;
    }




    /**
     *  根据题干+答案是否完全相同
     * @param questionTemplate
     * @param courseId
     * @param quesTypeId
     * @param classifyIdSecond
     * @return
     * @since 2019年6月24日
     * @auther duyu
     */
    private boolean checkCompleteQuestions(QuestionTemplate questionTemplate, String courseId, String quesTypeId, String classifyIdSecond) {

        QuestionAndOptionModel questionAndOptionModel = new QuestionAndOptionModel();
        BeanUtils.copyProperties(questionTemplate,questionAndOptionModel);
        // 课程id
        questionAndOptionModel.setCourseId(courseId);
        // 题型Id
        questionAndOptionModel.setQuestionTypeId(quesTypeId);
        // 章节Id
        questionAndOptionModel.setQuestionClassifyId(classifyIdSecond);

        List<QuestionAndOptionModel> models = questionDao.checkCompleteQuestions(questionAndOptionModel);
        if(CollectionUtils.isEmpty(models)){
            //返回 false 表示没有重复的试题，可以导入
            return false;
        }
        //返回 false 表示没有重复的试题，不可以导入
        return true;
    }


}
